<template>
  <div class="chat-app">
    <!-- 垂直导航栏 -->
    <nav class="chat-navigation">
      <button @click="switchView('chats')" :class="{ active: currentView === 'chats' }" title="会话">
        <i :class="[currentView === 'chats' ? 'fas fa-comment-dots' : 'far fa-comment-dots']"></i>
      </button>
      <button @click="switchView('contacts')" :class="{ active: currentView === 'contacts' }" title="联系人">
        <i :class="[currentView === 'contacts' ? 'fas fa-user' : 'far fa-user']"></i>
      </button>
      <button @click="switchView('groups')" :class="{ active: currentView === 'groups' }" title="群聊">
        <i :class="[currentView === 'groups' ? 'fas fa-users' : 'fas fa-users']"></i>
      </button>
    </nav>

    <!-- 搜索框 + 联系人或会话列表 -->
    <div class="list-container">
      <!-- 搜索框 -->
      <header class="search-bar">
        <div class="input-group">
          <i class="fas fa-search input-icon"></i>
          <input type="text" v-model="searchQuery" placeholder="搜索..." @input="performSearch"/>
        </div>
        <button class="add-group-button" title="创建群聊" @click="createGroupChat">
          <i class="fas fa-plus"></i>
        </button>
      </header>

      <!-- 联系人或会话列表 -->
      <aside class="chat-list" ref="chatList">
        <template v-if="currentView === 'chats'">
          <!-- 现有的聊天列表代码 -->
          <div v-for="(chat, index) in filteredChats" :key="index" @click="selectChat(chat)"
               :class="['chat-item', { 'active': selectedChat === chat }]">
            <div class="chat-item-content">
              <div class="avatar-container" :class="{ 'has-unread': chat.unreadCount > 0 }">
                <img :src="getAvatarUrl(chat.receiver)" alt="avatar" class="avatar"/>
                <span class="unread-count-badge" v-if="chat.unreadCount > 0">{{ chat.unreadCount }}</span>
              </div>
              <div class="chat-details">
                <div class="chat-info">
                  <span class="chat-name">{{ chat.name }}</span>
                  <span class="last-chat-time">{{ formatLastChatTime(chat.lastChatTime) }}</span>
                </div>
                <div class="latest-message" v-if="chat.messageContent">
                  {{ chat.messageContent }}
                </div>
              </div>
            </div>
          </div>
        </template>
        <template v-else-if="currentView === 'contacts'">
          <!-- 这里放置联系人列表 -->
          <div v-for="(contact, index) in filteredContacts" :key="index" @click="selectContact(contact)"
               :class="['chat-item', { 'active': selectedContact === contact }]">
            <div class="chat-item-content">
              <div class="avatar-container">
                <img :src="getAvatarUrl(contact.friendId)" alt="avatar" class="avatar"/>
              </div>
              <div class="chat-details">
                <div class="chat-info">
                  <span class="chat-name">{{ contact.showName }}</span>
                </div>
              </div>
            </div>
          </div>
        </template>
        <template v-else-if="currentView === 'groups'">
          <!-- 新增的群聊列表代码 -->
          <div v-for="(group, index) in filteredGroups" :key="index" @click="selectGroup(group)"
               :class="['chat-item', { 'active': selectedGroup === group }]">
            <div class="chat-item-content">
              <div class="avatar-container">
                <img :src="getAvatarUrl(group.groupName)" alt="avatar" class="avatar"/>
              </div>
              <div class="chat-details">
                <div class="chat-info">
                  <span class="chat-name">{{ group.groupName }}</span>
                </div>
              </div>
            </div>
          </div>
        </template>
      </aside>
    </div>

    <!-- 根据视图状态选择性地显示聊天窗口或联系人详情 -->
    <!--  联系人详情  -->
    <main v-if="currentView === 'contacts'" class="contact-details-view">
      <div v-if="selectedContact" class="contact-card">
        <header class="contact-header">
          <div class="avatar-container">
            <img :src="getAvatarUrl(selectedContact.friendId)" alt="avatar" class="avatar"/>
          </div>
          <div class="contact-info">
            <p class="remark">{{ selectedContact.remark || '无备注' }}</p>
            <p class="nickname">昵称：{{ selectedContact.showName }}</p>
            <p class="userId">用户ID：{{ selectedContact.userId }}</p>
            <p class="region">地区：{{ selectedContact.region || '未知' }}</p>
          </div>
          <div class="more-actions-wrapper">
            <button class="more-actions" @click="toggleMoreActions($event)">
              <i class="fas fa-ellipsis-h"></i>
            </button>
            <!-- 更多操作菜单（默认隐藏） -->
            <ul v-show="showActionsMenu" class="actions-menu" ref="actionsMenu">
              <li @click="deleteContact(selectedContact)">删除好友</li>
              <!-- 可以在这里添加更多操作选项 -->
            </ul>
          </div>
        </header>
        <hr/>
        <div class="button-group">
          <button @click="startChat(selectedContact)">发消息</button>
        </div>
      </div>
    </main>

    <!-- 添加群组视图 -->
    <!-- 群聊详情 -->
    <main v-else-if="currentView === 'groups'" class="group-details-view">
      <div  v-if="selectedGroup" class="group-detail-card">
        <header class="group-header">
          <div class="group-avatar-container">
            <img :src="getAvatarUrl(selectedGroup ? selectedGroup.groupName : '未知')" alt="group avatar" class="group-avatar"/>
            <p class="group-name">{{selectedGroup ?  selectedGroup.groupName : '未知'}}</p>
          </div>
          <hr />
        </header>

        <!-- 群信息 -->
        <section v-if="selectedGroup" class="group-info">
          <div class="info-line">
            <p>群主：{{ selectedGroup.ownerId }}</p>
            <p>群创建时间：{{ formatDate(selectedGroup.createTime) }}</p>
            <p>群人数：{{ groupMembers.length }}</p>
          </div>
          <hr />
        </section>

        <!-- 群成员列表 -->
        <section class="group-members">
          <ul class="members-list">
            <li v-for="(member, index) in [...groupMembers, { userId: 'add', userName: '添加群成员' }]" :key="index"
                :class="[index % 5 === 0 ? 'new-row' : '']">
              <div class="member-card">
                <img v-if="member.userId !== 'add'" :src="getAvatarUrl(member.userId)" alt="avatar" class="avatar"/>
                <button v-else class="add-member-btn">
                  <i class="fas fa-plus"></i>
                </button>
                <p class="name">{{ member.userName }}</p>
              </div>
            </li>
          </ul>
          <hr />
        </section>

        <!-- 发消息按钮 -->
        <div class="button-group">
          <button @click="startGroupChat(selectedGroup)">发消息</button>
        </div>
      </div>
    </main>

    <!--  聊天窗  -->
    <main v-else class="chat-view">
      <header class="chat-header">
        <span style="color: white;">{{ selectedChat ? selectedChat.name : '请选择聊天' }}</span>
      </header>
      <section class="chat-container">
        <div class="chat-window" ref="chatWindow">
          <!-- 根据 selectedChat.id 获取对应的消息列表 -->
          <div v-for="(message, index) in chatMessages[selectedChat?.id] || []" :key="index"
               :class="['chat-message', { 'self': isSelfMessage(message) }]">
            <!-- 对于别人发的消息 -->
            <img v-if="!isSelfMessage(message)" :src="getAvatarUrl(message.sendFrom)" alt="avatar" class="avatar"/>
            <div class="message-wrapper">
              <div class="header">
                <span v-if="isSelfMessage(message)" class="timestamp">{{ formatTimestamp(message.createTime) }}&nbsp;&nbsp;</span>
                <span class="sender">{{ message.sendFrom }}</span>
                <span v-if="!isSelfMessage(message)"
                      class="timestamp">&nbsp;&nbsp;{{ formatTimestamp(message.createTime) }}</span>
              </div>
              <div class="bubble">{{ message.messageContent }}</div>
            </div>
            <!-- 对于自己发的消息 -->
            <img v-if="isSelfMessage(message)" :src="getAvatarUrl(message.sendFrom)" alt="avatar"
                 class="avatar self-avatar"/>
          </div>
        </div>
        <!-- 输入框 -->
        <div class="chat-input">
          <input
              v-model="newMessageContent"
              @keyup.enter="sendMessage"
              placeholder="请输入内容..."
              class="input-field"
          />
          <button @click="sendMessage" class="send-button">发送</button>
        </div>
      </section>
    </main>
  </div>
</template>

<script>
import Cookie from "js-cookie";
import requestUtil from "@/network/request";
import * as chatAPI from '@/network/chat/chat';
import {mapState} from "vuex";
import {MessageBox} from "element-ui";


export default {
  data() {
    return {
      currentView: 'chats', // 默认显示会话列表
      contactsList: [], // 假设这是你的联系人列表
      chatMessages: {}, // 使用对象来存储每个聊天对象的消息列表
      newMessageContent: '', // 新消息内容
      currentUserId: Cookie.get('userId'), // 获取当前用户的 ID
      chatList: [
        {id: 'public-room', receiver: 'all', name: '公共聊天室', messages: [], unreadCount: 0}
      ], // 初始化聊天列表
      selectedChat: null, // 当前选中的聊天对象
      selectedContact: null,// 当前选中的联系人对象
      lastMessageIds: {}, // 记录所有房间的最后一条消息的ID
      loadingMore: false, // 控制是否正在加载更多消息
      scrollTimeout: null, // 用于防抖的定时器
      showActionsMenu: false, // 控制更多操作菜单的显示状态
      searchQuery: '',// 搜索框输入内容
      selectedGroup: null, // 新增用于保存选中的群聊
      groups: [], // 假设这是你从后端获取的群聊列表
      groupMembers: [],// 群成员
    };
  },
  methods: {
    /*切换会话/联系人*/
    switchView(view) {
      this.currentView = view;
      this.unbindScrollEvent(); // 移除旧的事件监听器
      this.$nextTick(() => {
        this.bindScrollEvent(); // 添加新的事件监听器
      });
    },
    /*点击切换联系人*/
    selectContact(contact) {
      this.selectedContact = contact;
    },
    /*发送消息*/
    async sendMessage() {
      const trimmedMessage = this.newMessageContent.trim();
      if (trimmedMessage) {
        let receiver;
        let chatType;

        // 判断是私聊还是群聊
        if (this.selectedChat.id === 'public-room') {
          // 公共聊天室
          receiver = 'all';
          chatType = 'GROUP';
        } else {
          // 私聊或其他类型的聊天
          receiver = this.selectedChat.receiver; // 假设 selectedChat.id 是接收者的ID
          chatType = 'PERSON'; // 或者根据实际情况调整
        }
        const chatMessage = {
          sendFrom: this.currentUserId, // 发送者的用户ID
          receiver: receiver,
          roomId: this.selectedChat.id,
          messageContent: trimmedMessage,
          chatType: chatType,
          messageType: 'TEXT',
        };

        // 发送消息到服务器
        try {
          const res = await chatAPI.sendMsgFun(chatMessage);
          if (res.code !== '0') {
            this.$message.error(res.msg);
          }
        } catch (error) {
          console.error('Error fetching post detail:', error);
          this.$message.error('获取帖子详情失败');
        } finally {
          this.loading = false;
        }

        // 清空输入框并滚动到底部
        this.newMessageContent = '';
        this.scrollToBottom();
      }
    },
    /*处理websocket推送的消息*/
    async handleMessage(data) {
      // 实现处理推送数据的逻辑
      console.log('Received data from chatRoom:', data);
      if (data.type === 4) {
        const chatId = data.data.roomId;
        const messageContent = data.data.messageContent;
        const createTime = data.data.createTime;
        // 确保 chatMessages 对象中有对应的 chatId 数组
        if (!this.chatMessages[chatId]) {
          this.$set(this.chatMessages, chatId, []);
        }
        this.chatMessages[chatId].push(data.data);
        // 检查当前会话列表中是否已有该聊天对象
        let chatItemIndex = this.chatList.findIndex(chat => chat.id === chatId);
        // 如果不存在，则创建新的聊天对象并添加到列表
        if (chatItemIndex === -1) {
          try {
            // 根据发送人Id查询他的信息
            let res = await chatAPI.getFriendInfoByUserId({friendId: data.data.sendFrom});
            let showName = res.code === '0' ? res.result.showName : '未知用户';

            // 创建新的聊天对象
            const newChatItem = {
              id: chatId,
              name: showName,
              messageContent,
              lastChatTime: createTime,
              unreadCount: this.selectedChat && this.selectedChat.id !== chatId ? 1 : 0,
              friendId: data.data.sendFrom
            };

            // 将新聊天项插入到列表的最前面
            this.chatList.unshift(newChatItem);
          } catch (error) {
            console.error('Error fetching friend info:', error);
          }
        } else {
          // 如果存在，更新现有聊天对象的信息
          let chatItem = this.chatList[chatItemIndex];
          chatItem.messageContent = messageContent;
          chatItem.lastChatTime = createTime;

          // 如果当前选中的聊天对象不是这个聊天对象，则增加未读数
          if (!this.selectedChat || (this.selectedChat && this.selectedChat.id !== chatId)) {
            chatItem.unreadCount += 1;
          } else {
            chatItem.unreadCount = 0;
          }

          // 将聊天项移动到列表的最前面
          this.chatList.splice(chatItemIndex, 1);
          this.chatList.unshift(chatItem);
        }
        // 如果当前选中的聊天对象是这个聊天对象，则滚动到底部显示最新消息
        if (this.selectedChat && this.selectedChat.id === chatId) {
          this.scrollToBottom();
        }

        // 保存更新后的消息到 IndexedDB
        await this.$chatDb.saveMessages(chatId, this.chatMessages[chatId]);
        // 保存更新后的聊天列表到 IndexedDB
        await this.$chatDb.saveChatList(this.chatList);
      }
    },
    /*时间戳格式转换*/
    formatTimestamp(timestamp) {
      return new Date(timestamp).toLocaleTimeString([], {hour: '2-digit', minute: '2-digit'});
    },
    /*将聊天记录滚动到最下方*/
    scrollToBottom() {
      this.$nextTick(() => {
        const chatWindow = this.$refs.chatWindow;
        if (chatWindow) { // 确保 chatWindow 存在
          chatWindow.scrollTop = chatWindow.scrollHeight;
        }
      });
    },
    /*获取头像*/
    getAvatarUrl(senderId) {
      // 根据 senderId 返回头像 URL，这里只是一个示例
      return `https://ui-avatars.com/api/?name=${senderId}&background=random`;
    },
    /*判断是否是自己发送的消息*/
    isSelfMessage(message) {
      // 判断消息是否来自当前用户
      return message.sendFrom === this.currentUserId;
    },
    /*选择聊天*/
    async selectChat(chat) {
      this.selectedChat = chat;
      const currentUnreadCount = chat.unreadCount;
      // 如果聊天有未读消息，重置未读计数
      if (chat.unreadCount > 0) {
        chat.unreadCount = 0;
      }
      try {
        this.loading = true;
        // 获取当前已有消息
        const existingMessages = await this.$chatDb.getAllMessages(chat.id);
        console.log('existingMessages',existingMessages)
        if (existingMessages.length !== 0 && currentUnreadCount === 0) {
          //有历史消息,并且未读数为0就不主动去查历史消息了
          this.scrollToBottom();
          return;
        }
        // 首次加载时，查询最新5条消息
        const messages = await this.fetchMessages(chat.id);
        if (messages.length === 0) {
          return;
        }
        // 更新最后一条消息的ID为新加载消息中最小的ID
        //this.lastMessageId = messages[messages.length - 1]?.id;
        // 反转消息顺序，使最新的消息在最下面
        messages.reverse();
        // 取最大Id，用来已读未读
        const latestMessage = messages[messages.length - 1];
        // 请求后端，标记消息为已读(可以再做优化)
        await chatAPI.readMessageByMaxId({roomId: chat.id, messageId: latestMessage.id});
        // 将获取到的新消息与现有消息合并并去重
        const mergedMessages = this.mergeNewMessagesWithoutDuplicates(existingMessages, messages);
        // 更新聊天消息列表
        this.$set(this.chatMessages, chat.id, mergedMessages);
        // 保存聊天记录到LocalStorage
        //localStorage.setItem(this.getStorageKey('chatMessages'), JSON.stringify(this.chatMessages));

        // 保存更新后的消息到 IndexedDB
        await this.$chatDb.saveMessages(chat.id, mergedMessages);
        // 保存更新后的聊天列表到 IndexedDB
        await this.$chatDb.saveChatList(this.chatList);
        this.scrollToBottom();
      } catch (error) {
        console.error('Error fetching chat history:', error);
        this.$message.error('获取聊天记录失败');
      } finally {
        this.loading = false;
      }
    },
    /*获取消息记录*/
    async fetchMessages(roomId, messageId) {
      // 如果提供了messageId，则作为游标进行分页查询
      const res = await chatAPI.getMessageByRoomIdFun({
        roomId: roomId,
        messageId: messageId,
        pageSize: 10
      });
      if (res.code === '0') {
        return res.result.messageList;
      } else {
        throw new Error(res.msg);
      }
    },
    /*辅助函数：合并两个消息列表并去除重复项，用于加载新消息*/
    mergeNewMessagesWithoutDuplicates(existingMessages, newMessages) {
      const existingIds = new Set(existingMessages.map(msg => msg.id));
      return [
        ...existingMessages,// 现有消息在前
        ...newMessages.filter(msg => !existingIds.has(msg.id))// 新消息在后
      ];
    },
    /*辅助函数：合并两个消息列表并去除重复项，用于加载历史消息*/
    mergeOldMessagesWithoutDuplicates(existingMessages, oldMessages) {
      const existingIds = new Set(existingMessages.map(msg => msg.id));
      return [
        ...oldMessages.filter(msg => !existingIds.has(msg.id)),// 旧消息在前（顶部）
        ...existingMessages// 现有消息在后
      ];
    },
    /*当滚动条到达最顶上时调用后台获取历史消息*/
    handleScroll(event) {
      const chatWindow = event.target;

      // 清除之前的定时器以实现防抖效果
      if (this.scrollTimeout) {
        clearTimeout(this.scrollTimeout);
      }

      this.scrollTimeout = setTimeout(() => {
        // 当用户滚动到顶部附近时触发加载更多消息
        if (!this.loadingMore && chatWindow.scrollTop <= 100) {
          this.loadMoreMessages();
        }
      }, 300); // 减少延迟时间以更快响应
    },
    /*加载更多消息*/
    async loadMoreMessages() {
      if (this.loadingMore || !this.selectedChat) return;

      try {
        this.loadingMore = true;

        // 获取聊天窗口和当前可见的第一条消息
        const chatWindow = this.$refs.chatWindow;
        const firstVisibleMessage = chatWindow.querySelector('.chat-message:first-child');

        // 记录当前的 scrollTop 和第一个可见消息的偏移量
        let currentScrollTop = chatWindow.scrollTop;
        let topOffsetBefore = 0;
        if (firstVisibleMessage) {
          topOffsetBefore = firstVisibleMessage.getBoundingClientRect().top - chatWindow.getBoundingClientRect().top + chatWindow.scrollTop;
        }

        //先根据房间id从消息列表里获取消息，然后将最久的消息id值去覆盖
        const existingMessages = this.chatMessages[this.selectedChat.id] || [];
        if (existingMessages.length > 0) {
          this.lastMessageIds[this.selectedChat.id] = existingMessages[0].id;
        }

        // 使用最后一条消息的ID作为游标加载更多消息
        const messages = await this.fetchMessages(this.selectedChat.id, this.lastMessageIds[this.selectedChat.id]);

        if (messages.length > 0) {
          // 更新最后一条消息的ID为新加载消息中最小的ID
          this.lastMessageIds[this.selectedChat.id] = messages[messages.length - 1]?.id;
          // 确保新加载的消息按照时间升序排列
          messages.reverse();
          this.$set(
              this.chatMessages,
              this.selectedChat.id,
              this.mergeOldMessagesWithoutDuplicates(this.chatMessages[this.selectedChat.id], messages)
          );

          // 等待DOM更新完成
          this.$nextTick(() => {
            // 再次获取当前可见的第一条消息（现在是新加载的消息之一）
            const newFirstVisibleMessage = chatWindow.querySelector('.chat-message:first-child');

            // 如果有原始的第一个可见消息，则找到它在新列表中的位置
            let originalFirstMessageHeight = 0;
            if (firstVisibleMessage) {
              const originalFirstMessage = chatWindow.querySelector(`.chat-message[data-id="${firstVisibleMessage?.dataset.id}"]`);
              if (originalFirstMessage) {
                originalFirstMessageHeight = originalFirstMessage.offsetHeight;
              }
            }

            // 根据原始偏移量和新增消息的高度调整滚动位置
            if (typeof topOffsetBefore === 'number' && newFirstVisibleMessage) {
              // 新增消息的总高度
              const addedMessagesHeight = Array.from(chatWindow.querySelectorAll('.chat-message'))
                  .slice(0, messages.length)
                  .reduce((acc, msg) => acc + msg.offsetHeight, 0);

              // 设置 scrollTop 以保持原来的顶部消息在同一位置
              chatWindow.scrollTop = currentScrollTop + addedMessagesHeight - originalFirstMessageHeight;
            }
          });
          // 保存会话列表到LocalStorage
          //localStorage.setItem(this.getStorageKey('chatMessages'), JSON.stringify(this.chatMessages));
          // 保存更新后的消息到 IndexedDB
          await this.$chatDb.saveMessages(this.selectedChat.id, messages);
        } else {
          console.log('No more messages to load');
          this.$message({
            message: "没有更多历史消息...",
            type: 'success',
            duration: 2000 // 设置显示时间为 600 毫秒（0.6 秒）
          })
        }
      } catch (error) {
        console.error('Error loading more messages:', error);
        this.$message.error('加载更多聊天记录失败');
      } finally {
        this.loadingMore = false;
      }
    },
    /*获取好友、联系人列表*/
    getFriendList() { //获取
      chatAPI.getFriends({
        currentPage: 1,
        pageSize: 20
      }).then(res => {
        //这里将数据加载到联系人列表
        if (res.code === '0') { // 假设'0'表示成功
          this.contactsList = res.result.chatList || []; // 将数据加载到联系人列表
        } else {
          console.error('Failed to fetch friends list:', res.message);
        }
      }).catch(error => {
        console.error('Error fetching friends list:', error);
      });
    },
    /*从联系人页面跳转到去聊天的方法*/
    async startChat(contact) {
      let chatEntry = null;

      // 检查是否有已存在的会话
      const existingChatIndex = this.chatList.findIndex(chat => chat.receiver === contact.friendId);
      if (existingChatIndex !== -1) {
        // 如果存在，则选择该会话
        chatEntry = this.chatList[existingChatIndex];
      } else {
        // 如果不存在，则调用后台API获取必要数据并创建新会话
        try {
          const response = await this.fetchChatDetails(contact.friendId);
          if (response) {
            const newChatItem = {
              id: response.roomId,
              name: response.showName,
              messageContent: response.messageContent,
              lastChatTime: response.lastChatTime,
              unreadCount: 0,
              messages: [],
              receiver: contact.friendId,
            };
            // 将新聊天项插入到列表的最前面
            this.chatList.unshift(newChatItem);
            // 更新 chatEntry 为新创建的聊天项
            chatEntry = newChatItem;
            // 保存会话列表到LocalStorage
            //localStorage.setItem(this.getStorageKey('chatList'), JSON.stringify(this.chatList));
            // 保存新的聊天项到 IndexedDB
            await this.$chatDb.saveChatList(this.chatList);
          }
        } catch (error) {
          console.error('Failed to fetch chat details:', error);
          return;
        }
      }
      // 选择会话并切换到聊天视图
      this.switchView('chats');
      await this.selectChat(chatEntry);
    },
    /*从群聊页面跳转到去聊天的方法*/
    async startGroupChat(group) {
      let chatEntry = null;

      // 检查是否有已存在的会话
      const existingChatIndex = this.chatList.findIndex(chat => chat.id === group.roomId);
      if (existingChatIndex !== -1) {
        // 如果存在，则选择该会话
        chatEntry = this.chatList[existingChatIndex];
      } else {
        // 如果不存在，创建新会话
        const newChatItem = {
          id: group.id,
          name: group.groupName,
          unreadCount: 0,
          receiver: 'all',
        };
        // 将新聊天项插入到列表的最前面
        this.chatList.unshift(newChatItem);
        // 更新 chatEntry 为新创建的聊天项
        chatEntry = newChatItem;
      }
      // 选择会话并切换到聊天视图
      this.switchView('chats');
      await this.selectChat(chatEntry);
    },
    /*获取好友聊天信息，用于跳转到会话列表*/
    fetchChatDetails(friendId) {
      return chatAPI.getFriendChatInfo({friendId: friendId}).then(res => {
        if (res.code === '0') {
          return res.result;
        }
      });
    },
    /*删除会话*/
    deleteContact(contact) {
      this.showActionsMenu = false; // 关闭菜单
      // 删除联系人的逻辑
      // 这里可以调用API来删除联系人，或者仅从前端移除
      MessageBox.confirm('确定要删除此联系人吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        // 删除联系人的逻辑
        this.contactsList = this.contactsList.filter(c => c.friendId !== contact.friendId);
        this.selectedContact = null;
      }).catch(() => {
        // 用户取消删除操作
      });
    },
    /*获取未读消息列表*/
    getUnreadMessages() {
      requestUtil.post('/message/unread/list', {
        receiver: this.currentUserId,
      }).then(res => {
        if (res.code === '0') {
          const list = res.result.messageList;
          // 更新或添加聊天对象到现有聊天列表
          list.forEach(item => {
            const existingChatIndex = this.chatList.findIndex(chat => chat.id === item.roomId);
            if (existingChatIndex !== -1) {
              // 更新已有的聊天对象
              this.$set(this.chatList, existingChatIndex, {
                ...this.chatList[existingChatIndex],
                ...item,
                id: item.roomId,
                receiver: item.friendId,
                name: item.showName,
                messageContent: item.messageContent,
                unreadCount: item.unreadCount,
                lastChatTime: item.lastChatTime,
                messages: this.chatMessages[item.roomId] || [] // 确保消息列表不被覆盖
              });
            } else {
              // 添加新的聊天对象
              this.chatList.push({
                ...item,
                id: item.roomId,
                roomId: item.roomId,
                receiver: item.friendId,
                name: item.showName,
                messageContent: item.messageContent,
                unreadCount: item.unreadCount,
                lastChatTime: item.lastChatTime,
                messages: [] // 每个聊天对象有自己的消息列表
              });
            }
          });

          // 保存更新后的聊天列表到LocalStorage
          //localStorage.setItem(this.getStorageKey('chatList'), JSON.stringify(this.chatList));
          // 保存新的聊天项到 IndexedDB
          this.$chatDb.saveChatList(this.chatList);
        } else {
          this.$message.error(res.msg);
        }
      })
    },
    /*最近聊天时间的格式转换*/
    formatLastChatTime(lastChatTime) {
      // 将 lastChatTime 转换为 Date 对象，假设它是 UTC 时间戳
      const chatDate = new Date(parseInt(lastChatTime));
      // 获取当前时间，使用本地时区
      const now = new Date();
      // 计算两个日期之间的差异
      const diffInDays = Math.floor((now - chatDate) / (1000 * 60 * 60 * 24));
      if (diffInDays === 0) {
        // 如果是当天的，则展示时间，例如10:20
        return chatDate.toLocaleTimeString([], {hour: '2-digit', minute: '2-digit'});
      } else if (diffInDays === 1) {
        // 如果是昨天的，展示昨天+时间，例如 昨天10:20
        return `昨天 ${chatDate.toLocaleTimeString([], {hour: '2-digit', minute: '2-digit'})}`;
      } else if (diffInDays < 7) {
        // 如果是一周内的，展示周几，例如 周三 10:20
        const daysOfWeek = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
        const dayOfWeek = daysOfWeek[chatDate.getUTCDay()]; // 使用 getUTCDay 来获取 UTC 的星期几
        return `${dayOfWeek} ${chatDate.toLocaleTimeString([], {hour: '2-digit', minute: '2-digit'})}`;
      } else {
        // 如果是一周前的，展示日期，例如 2024/10/20
        return chatDate.toLocaleDateString('zh-CN', {year: 'numeric', month: '2-digit', day: '2-digit'});
      }
    },
    /*绑定滚动事件监听器*/
    bindScrollEvent() {
      const chatWindow = this.$refs.chatWindow;
      if (chatWindow) {
        chatWindow.addEventListener('scroll', this.handleScroll);
      }
    },
    /*解除绑定滚动事件监听器*/
    unbindScrollEvent() {
      const chatWindow = this.$refs.chatWindow;
      if (chatWindow) {
        chatWindow.removeEventListener('scroll', this.handleScroll);
      }
    },
    /*弹出操作菜单*/
    toggleMoreActions(event) {
      this.showActionsMenu = !this.showActionsMenu;
      if (this.showActionsMenu) {
        // 添加全局点击事件监听器
        document.addEventListener('click', this.closeMenuOnClickOutside);
        this.$nextTick(() => {
          if (this.$refs.actionsMenu) {
            this.positionActionsMenu(event);
          } else {
            console.error('actionsMenu ref not found');
          }
        });
      } else {
        // 移除全局点击事件监听器
        document.removeEventListener('click', this.closeMenuOnClickOutside);
        // 如果关闭菜单，则重置样式
        if (this.$refs.actionsMenu) {
          this.$refs.actionsMenu.style.left = '';
          this.$refs.actionsMenu.style.top = '';
        }
      }
    },
    /*计算操作菜单的位置*/
    positionActionsMenu(event) {
      const menu = this.$refs.actionsMenu;
      if (!menu) return;

      // 简化位置计算，先让它简单地出现在按钮下方
      menu.style.left = '0';
      menu.style.top = `${event.target.offsetHeight}px`;
    },
    /*点击外部关闭操作菜单*/
    closeMenuOnClickOutside(event) {
      // 如果点击发生在菜单或按钮外部，则关闭菜单
      const menu = this.$refs.actionsMenu;
      const button = event.target.closest('.more-actions');
      if (menu && !menu.contains(event.target) && !button) {
        this.showActionsMenu = false;
        // 移除全局点击事件监听器
        document.removeEventListener('click', this.closeMenuOnClickOutside);
      }
    },
    /*处理搜索*/
    performSearch(event) {
      // 如果需要执行额外的搜索逻辑，可以在这里处理
      console.log(event)
    },
    /*创建群聊*/
    createGroupChat() {
      // 创建群聊的逻辑
      alert('创建群聊功能尚未实现');
    },
    /*选择群聊*/
    selectGroup(group) {
      this.selectedGroup = group;
      console.log(this.selectedGroup)
      //查询群成员
      chatAPI.getGroupDetails({groupId: group.id}).then(res => {
        if (res.code === '0') { // 假设'0'表示成功
          const groupInfo = res.result.groupInfo;
          this.groupMembers = (res.result.userInfoList || []).map(item => ({
            userId: item.userId,
            userName: item.userName,
          }));
          this.selectedGroup.ownerId = groupInfo.groupOwnerId;
          this.selectedGroup.memberCount = groupInfo.groupMemberCount;
          this.selectedGroup.createTime = groupInfo.createTime;
        } else {
          console.error('Failed to fetch group list:', res.message);
        }

      })
    },
    /*获取群聊列表*/
    getGroupList() {
      chatAPI.getGroups({}).then(res => {
        //这里将数据加载到联系人列表
        if (res.code === '0') { // 假设'0'表示成功
          this.groups = (res.result.groupList || []).map(item => ({
            id: item.groupId,
            roomId: item.groupId,
            receiver: 'all',
            groupName: item.groupName,
            memberCount: item.memberCount,
            // 如果有其他需要映射的属性，可以在这里添加
          }));

          // 如果你需要将原始数据也存储下来，可以这样做：
          // this.groupList = res.result.groupList || [];
        } else {
          console.error('Failed to fetch group list:', res.message);
        }
      }).catch(error => {
        console.error('Error fetching group list:', error);
      });
    },
    // 格式化日期的方法
    formatDate(dateString) {
      const options = { year: 'numeric', month: 'long', day: 'numeric' };
      return new Date(dateString).toLocaleDateString(undefined, options);
    },
    // 在初始化方法中添加加载本地存储的消息
    init() {
      // 尝试从LocalStorage加载聊天列表，并确保其为数组
      this.initChatList();
      // 尝试从LocalStorage加载好友列表
      //this.contactsList = JSON.parse(localStorage.getItem(this.getStorageKey('contactsList'))) || [];
      // 尝试从LocalStorage加载群聊列表
      //this.groups = JSON.parse(localStorage.getItem(this.getStorageKey('groups'))) || [];
      // 尝试从LocalStorage加载所有聊天记录
      //this.chatMessages = JSON.parse(localStorage.getItem(this.getStorageKey('chatMessages'))) || {};
    },
    /*初始化会话列表*/
    async initChatList() {
      try {
        this.chatList = await this.$chatDb.loadChatList();

        if (!Array.isArray(this.chatList)) {
          console.warn('Invalid data type for chatList, resetting to an empty array.');
          this.chatList = [];
        }

        const hasPublicRoom = this.chatList.some(chat => chat.id === 'public-room');
        if (this.chatList.length === 0 || !hasPublicRoom) {
          console.log('no public-room...')
          this.chatList = [
            { id: 'public-room', receiver: 'all', name: '公共聊天室', messages: [], unreadCount: 0 },
            ...this.chatList
          ];
          await this.$chatDb.saveChatList(this.chatList); // 保存更新后的聊天列表
        }

        this.chatList.forEach(async chat => {
          if (!this.chatMessages[chat.id]) {
            const messages = await this.$chatDb.getAllMessages(chat.id);
            this.$set(this.chatMessages, chat.id, messages || []);
          }
        });
      } catch (error) {
        console.warn('Failed to initialize chat list:', error);
      }
    },
    /*获取缓存key*/
    getStorageKey(key){
      return this.currentUserId + '_' + key;
    }
  },
  mounted() {
    this.getFriendList();
    this.getGroupList();
    this.getUnreadMessages();
    this.init();
    this.$nextTick(() => {
      // 确保 DOM 已经更新后再绑定滚动事件监听器
      this.bindScrollEvent();
    });
  },
  beforeDestroy() {
    // 移除滚动事件监听器，防止内存泄漏
    this.unbindScrollEvent();
  },
  computed: {
    ...mapState('websocket', ['connected', 'messages']),
    // 根据搜索查询过滤联系人列表
    filteredContacts() {
      if (!this.searchQuery) return this.contactsList;
      const query = this.searchQuery.toLowerCase();
      return this.contactsList.filter(contact =>
          contact.showName.toLowerCase().includes(query)
      );
    },
    // 根据搜索查询过滤聊天列表
    filteredChats() {
      if (!this.searchQuery) return this.chatList;
      const query = this.searchQuery.toLowerCase();
      return this.chatList.filter(chat =>
          chat.name.toLowerCase().includes(query)
      );
    },
    // 根据搜索查询过滤群聊列表
    filteredGroups() {
      if (!this.searchQuery) return this.groups;
      return this.groups.filter(group =>
          group.groupName.toLowerCase().includes(this.searchQuery.toLowerCase())
      );
    },
  },
  watch: {
    messages(newMessages) {
      // 当有新消息时触发
      newMessages.forEach((message, index) => {
        if (index === newMessages.length - 1) {
          // 只处理最新的消息
          this.handleMessage(message);
        }
      });
    }
  }
};
</script>

<style scoped>
/* 导航栏样式 */
.chat-navigation {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 5px 0; /* 减少上下内边距 */
  background-color: rgb(39, 42, 55);
  width: 45px; /* 固定宽度 */
  /* border-right: 1px solid #e9ecef; */
}

.chat-navigation button {
  background: none;
  border: none;
  padding: 10px;
  margin: 5px 0;
  cursor: pointer;
  width: 100%; /* 按钮宽度占满父容器 */
  box-sizing: border-box; /* 确保内边距和边框包含在元素的总宽度中 */
  font-size: 24px; /* 调整图标大小 */
  color: #e4dcdc; /* 默认颜色 */
  transition: color 0.3s ease, background-color 0.3s ease;
}

.chat-navigation button i {
  font-size: inherit; /* 继承按钮的字体大小 */
  display: block; /* 确保图标占据整个按钮空间 */
  line-height: 24px; /* 对齐图标中心 */
}

.chat-navigation button:hover {
  color: #2fff00; /* 鼠标悬停时的颜色 */
  background-color: rgba(255, 255, 255, 0.1); /* 轻微的背景色变化 */
  border-radius: 8px;
}

.chat-navigation button.active {
  color: #007bff; /* 激活状态的颜色 */
  background-color: rgba(255, 255, 255, 0.1); /* 轻微的背景色变化 */
  border-radius: 8px;
}

main {
  flex-grow: 1; /* 占用剩余的所有空间 */
}

/* 联系人 start*/
.contact-details-view {
  display: flex;
  justify-content: center;
  height: 100%;
}

.group-view {
  display: flex;
  justify-content: center;
  height: 100%;
  background-color: red;
}

.contact-card {
  background-color: white;
  border-radius: 8px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  width: 100%;
  height: 200px;
  max-width: 500px;
  margin-top: 50px;
  padding: 20px;
  position: relative; /* 使子元素可以相对此元素进行绝对定位 */
}

.contact-header {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
}

.avatar-container {
  margin-right: 15px;
}

.avatar {
  width: 60px;
  height: 60px;
  border-radius: 50%;
}

.contact-info {
  flex-grow: 1;
}

.contact-info p {
  margin: 0;
  line-height: 1.5;
}

.remark {
  font-weight: bold;
}

.nickname,
.userId,
.region {
  color: #555;
}

.more-actions-wrapper {
  position: relative; /* 使子元素可以相对此元素进行绝对定位 */
}

.more-actions {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 1.2em;
  color: #333;
}

.actions-menu {
  position: absolute;
  background-color: white;
  border: 1px solid #ccc;
  border-radius: 4px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  list-style: none;
  padding: 0; /* 移除外部填充 */
  margin: 0;
  z-index: 9999; /* 确保菜单显示在其他元素之上 */
  left: 0;
  top: 0;
  width: 100px; /* 固定宽度，可根据需要调整 */
}

.actions-menu li {
  padding-left: 20px; /* 统一的内边距 */
  cursor: pointer;
  white-space: nowrap;
  text-align: left;
  display: flex;
  align-items: center; /* 垂直居中 */
  justify-content: flex-start; /* 水平左对齐 */
  width: 100%; /* 确保每一项占据整个宽度 */
  box-sizing: border-box; /* 包含 padding 在内的总宽 */
}

.actions-menu li:hover {
  background-color: #f0f0f0;
}

.button-group {
  text-align: center;
}

.button-group button {
  background-color: #4CAF50;
  color: white;
  border: none;
//padding: 10px 20px; font-size: 16px;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.3s;
}

.button-group button:hover {
  background-color: #45a049;
}

/* 联系人 end*/

/* 聊天界面 */
.chat-app {
  display: flex;
  height: calc(100vh - 140px);
  background-color: rgb(39, 42, 55);
  padding: 10px;
  border-radius: 15px;
}

.chat-list {
  width: 250px;
//border-right: 1px solid #ccc; flex-grow: 1;
  overflow-y: auto;
  background-color: rgb(39, 42, 55);
  padding: 10px;
  height: calc(100% - 20px);
//border-radius: 15px;
}

.chat-view {
  flex-grow: 1;
  display: flex;
  flex-direction: column;
  height: 100%;
  border-radius: 15px;
  margin-left: 5px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); /* 添加阴影 */
}

.chat-header {
  padding: 10px;
//border-bottom: 1px solid #ccc; background-color: rgb(91, 94, 105);
  font-weight: bold;
  flex-shrink: 0; /* 确保头部不被压缩 */
  border-top-left-radius: 15px; /* 上左圆角 */
  border-top-right-radius: 15px; /* 上右圆角 */
}

.chat-container {
  display: flex;
  flex-direction: column;
  flex-grow: 1;
  height: 0; /* 强制计算剩余空间 */
}

.chat-window {
  flex-grow: 1;
  overflow-y: auto;
  padding: 10px;
  /*border-bottom: 1px solid #ccc;*/
  background-color: rgb(50, 54, 68);
}

/*滚动条*/
.chat-window::-webkit-scrollbar {
  width: 6px;
}

.chat-window::-webkit-scrollbar-thumb {
  background-color: white; /* 滚动条颜色 */
  border-radius: 4px;
}

.chat-window::-webkit-scrollbar-track {
  background-color: transparent;
}

.chat-window::-webkit-scrollbar-button {
  display: none;
}

/*滚动条*/

.chat-message {
  display: flex;
  align-items: flex-start;
  margin-bottom: 10px;
  width: 100%; /* 确保消息占满整个宽度 */
}

/* 自己发的消息靠右显示 */

.chat-message.self {
  justify-content: flex-end;
}

.avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  margin-right: 10px;
}

/* 自己的头像靠右 */

.self-avatar {
  margin-left: 10px;
  margin-right: 0;
}

.message-wrapper {
  max-width: 80%; /* 控制消息的最大宽度 */
  display: flex;
  flex-direction: column;
}

.header {
  display: flex;
  align-items: center;
  margin-bottom: 5px;
}

.sender {
  color: white;
  font-weight: bold;
}

.timestamp {
  color: #999;
  font-size: 0.8em;
}

.bubble {
  background-color: #e1ffc1;
  border-radius: 10px;
  padding: 8px 12px;
  display: inline-block;
  word-wrap: break-word;
  line-height: 1.4;
}

/* 自己发的消息气泡背景色 */

.chat-message.self .bubble {
  background-color: #d1eaff;
}

/* 自己发的消息中 header 的样式 */

.chat-message.self .header {
  justify-content: flex-end; /* 文本靠右 */
}

/* 确保别人发的消息中，头像在左边，内容在右边 */

.chat-message:not(.self) {
  justify-content: flex-start;
}

.chat-input {
  display: flex;
  padding: 10px;
  background-color: rgb(50, 54, 68);
  box-shadow: 0 -1px 5px rgba(0, 0, 0, 0.1);
  position: sticky;
  bottom: 0;
  z-index: 1;
  flex-shrink: 0; /* 确保输入框不被压缩 */
  border-bottom-left-radius: 15px; /* 上左圆角 */
  border-bottom-right-radius: 15px; /* 上右圆角 */
}

.input-field {
  flex-grow: 1;
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 4px;
  margin-right: 5px;
}

.send-button {
  padding: 10px 20px;
  background-color: #28a745;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.3s;
}

.send-button:hover {
  background-color: #218838;
}

/*联系人列表样式*/
.chat-item {
  display: flex;
  align-items: flex-start;
  padding: 10px;
  cursor: pointer;
  transition: background-color 0.3s;
  border-radius: 20px;
}

.chat-item:hover, .chat-item.active {
//background-color: #e9ecef; background-color: darkseagreen;
}

.chat-item-content {
  display: flex;
  width: 100%;
  align-items: flex-start;
}

.avatar-container {
  position: relative; /* 确保 unread-count-badge 相对于头像定位 */
  margin-right: 10px;
}

.avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
}

.unread-count-badge {
  position: absolute;
  top: -5px;
  right: -5px;
  background-color: #f44336;
  color: white;
  border-radius: 50%;
  padding: 2px 6px;
  font-size: 0.8em;
  line-height: 1;
}

.chat-details {
  flex-grow: 1;
  display: grid;
  grid-template-rows: auto auto;
  gap: 5px;
}

.chat-info {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  justify-content: space-between;
}

.chat-name {
  font-weight: bold;
  color: white;
}

.last-chat-time {
  color: #999;
  font-size: 0.8em;
  text-align: right;
  min-width: 70px; /* 给时间留出足够空间 */
}

.latest-message {
  color: #757575;
  font-size: 0.5em;
  white-space: nowrap; /* 防止换行 */
  overflow: hidden; /* 隐藏溢出的内容 */
  text-overflow: ellipsis; /* 使用省略号表示被隐藏的文字 */
}

/*搜索框相关*/
.list-container {
  display: flex;
  flex-direction: column;
  width: 270px; /* 设置为适合你应用的宽度 */
//border-right: 1px solid #ddd;
}

.search-bar {
  padding: 8px;
//border-bottom: 1px solid #ddd; display: flex;
  align-items: center;
  width: 100%;
  box-sizing: border-box; /* 确保 padding 和 border 包括在 width 内 */
}

.input-group {
  position: relative;
  display: flex;
  flex-grow: 1;
  box-sizing: border-box; /* 确保 padding 和 border 包括在 width 内 */
}

.input-icon {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: #999;
}

.search-bar input {
  flex-grow: 1; /* 让输入框占据剩余空间 */
  padding: 6px 10px 6px 30px; /* 左边留出空间给图标 */
  border-radius: 4px;
  border: 1px solid #ccc;
  box-sizing: border-box; /* 确保内边距和边框算在元素的总宽高之内 */
}

.add-group-button {
  margin-left: 8px;
  padding: 6px 12px;
  background-color: #4CAF50;
  color: white;
  border: none;
  cursor: pointer;
  border-radius: 4px;
  transition: background-color 0.3s;
  min-width: 20px; /* 固定按钮的最小宽度 */
  white-space: nowrap; /* 防止按钮文本换行 */
  box-sizing: border-box; /* 确保 padding 和 border 包括在 width 内 */
}

.add-group-button:hover {
  background-color: #45a049;
}

/*搜索框相关*/

/*群组相关*/
/* 群聊详情视图 */
.group-details-view {
  padding: 1rem;
}

.group-details-view p {
  color: black;
}

/*群信息展示*/
.group-detail-card {
  background-color: white;
  border-radius: 10px;
}

/* 群头像容器 */
.group-avatar-container {
  text-align: center;
  margin-bottom: 1rem;
}
.group-avatar {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  margin-bottom: 0.5rem;
}
.group-name {
  font-size: 1.2rem;
  font-weight: bold;
}

/* 群信息行 */
.info-line {
  display: flex;
  justify-content: space-between;
  padding: 0.5rem 0;
}
.info-line p {
  margin: 0;
}

/* 群成员列表 */
.members-list {
  display: flex;
  flex-wrap: wrap;
  list-style-type: none;
  padding: 0;
}
.member-card {
  flex: 0 0 calc(20% - 10px); /* 每行5个成员，减去边距 */
  margin: 5px;
  text-align: center;
  position: relative;
}
.member-card img,
.add-member-btn {
  width: 48px;
  height: 48px;
  border-radius: 50%;
}
.add-member-btn {
  background-color: #e0e0e0;
  border: none;
  cursor: pointer;
  color: #333;
  display: flex;
  align-items: center;
  justify-content: center;
}
.add-member-btn i {
  font-size: 1.5rem;
}

/* 按钮组 */
.button-group {
  margin-top: 1rem;
  text-align: center;
}
.button-group button {
  padding: 0.75rem 1.5rem;
  font-size: 1rem;
  cursor: pointer;
}

/*群组相关*/
</style>